package com.jwater.core.net;

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.jwater.core.common.S;
import com.jwater.core.serialize.SerializeFactory;

import jwater.org.apache.mina.core.buffer.IoBuffer;
import jwater.org.springframework.util.StringUtils;
/**
 * @description:
 * @author: jnner
 * @createDate: 2021/2/5
 * @version: 1.0
 */
public class ReturnPacket implements Serializable {
	private static final long serialVersionUID = -5839393473551650087L;

	private static Map<String, Class<?>> clazzCache = new ConcurrentHashMap<>();

	private short serializeType = SerializeFactory.DEFAULT_SERIALIZE_TYPE;
	private short errorCode = 0;// 错误码,0正常
	private String errorMsg = "";// 执行异常
	private String returnClazzName = "";// 返回对的类名
	private Object returnObj;// 返回值对象

	public byte[] serialize() throws Exception {
		serializeType = SerializeFactory.getSerializeType(returnObj);
		byte[] errorMsgBytes = errorMsg.getBytes(S.charset);
		byte[] returnClazzNameBytes = returnClazzName.getBytes(S.charset);
		byte[] data = SerializeFactory.getSerializeService(serializeType).serialize(returnObj);
		IoBuffer buffer = IoBuffer.allocate(16 + errorMsgBytes.length + returnClazzNameBytes.length + data.length);
		buffer.putShort(serializeType);
		buffer.putShort(errorCode);
		buffer.putInt(errorMsgBytes.length);
		if (errorMsgBytes.length > 0) {
			buffer.put(errorMsgBytes);
		}
		buffer.putInt(returnClazzNameBytes.length);
		if (returnClazzNameBytes.length > 0) {
			buffer.put(returnClazzNameBytes);
		}
		buffer.putInt(data.length);
		if (data.length > 0) {
			buffer.put(data);
		}
		return buffer.array();
	}

	public ReturnPacket deserialize(byte[] data) throws Exception {
		IoBuffer buffer = IoBuffer.wrap(data);
		serializeType = buffer.getShort();
		errorCode = buffer.getShort();

		byte[] bytes = null;
		int len = buffer.getInt();
		if (len > 0) {
			bytes = new byte[len];
			buffer.get(bytes);
			errorMsg = new String(bytes, 0, bytes.length, S.charset);
		}

		len = buffer.getInt();
		if (len > 0) {
			bytes = new byte[len];
			buffer.get(bytes);
			returnClazzName = new String(bytes, 0, bytes.length, S.charset);
		}

		len = buffer.getInt();
		if (len > 0) {
			bytes = new byte[len];
			buffer.get(bytes);

			if (!StringUtils.isEmpty(returnClazzName)) {
				Class<?> clazz = clazzCache.get(returnClazzName);
				if (clazz == null) {
					clazz = Class.forName(returnClazzName);
					clazzCache.put(returnClazzName, clazz);
				}
				returnObj = SerializeFactory.getSerializeService(serializeType).deserialize(bytes, clazz);
			}
		}
		return this;
	}

	public short getSerializeType() {
		return serializeType;
	}

	public void setSerializeType(short serializeType) {
		this.serializeType = serializeType;
	}

	public String getReturnClazzName() {
		return returnClazzName;
	}

	public void setReturnClazzName(String returnClazzName) {
		this.returnClazzName = returnClazzName;
	}

	public short getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(short errorCode) {
		this.errorCode = errorCode;
	}

	public String getErrorMsg() {
		return errorMsg;
	}

	public void setErrorMsg(String errorMsg) {
		this.errorMsg = errorMsg;
	}

	public Object getReturnObj() {
		return returnObj;
	}

	public void setReturnObj(Object returnObj) {
		this.returnObj = returnObj;
	}

	@Override
	public String toString() {
		return "ReturnPacket [serializeType=" + serializeType + ", errorCode=" + errorCode + ", errorMsg=" + errorMsg
				+ ", returnClazzName=" + returnClazzName + ", returnObj=" + returnObj + "]";
	}
}
